/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sqlserver_rpc.c                                               */
/*  NOTE      = 根据不同procedure ID解析RPC                                   */
/*  DATE      = 2014/10/10 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <string.h>

#include "sqlserver_core.h"
#include "sqlserver_common.h"
#include "sqlserver_base_type.h"

#define MSSQL_MAX_UID_LEN         32

/*******************************************************************************
*  FUNC     :  设置TDS版本号
*  ARGS     :  p_st_statement (statement)
*           :  l_cursor_id (cursor id)
*  RTN      :  (Mssql_cursor *)
*  NOTE     :
*******************************************************************************/
FR_STATIC void __sqlserver_set_tds_ver(L7_req_sqlserver *p_st_req
                                   , L7session_sqlserver *p_st_session)
{
    if (p_st_session->i_cli_tds_ver == MSSQL_TDS_VER_NULL)
    {
        if (p_st_req->i_cli_tds_min_ver_tmp < p_st_req->i_cli_tds_max_ver_tmp)
        {
            p_st_session->i_cli_tds_ver = p_st_req->i_cli_tds_ver_tmp;
            p_st_session->i_cli_tds_min_ver = p_st_req->i_cli_tds_min_ver_tmp;
            p_st_session->i_cli_tds_max_ver = p_st_req->i_cli_tds_max_ver_tmp;
        }
        else if (p_st_req->i_cli_tds_min_ver_tmp == p_st_req->i_cli_tds_max_ver_tmp)
        {
            p_st_session->i_cli_tds_ver = p_st_req->i_cli_tds_min_ver_tmp;
            p_st_session->i_cli_tds_min_ver = p_st_req->i_cli_tds_min_ver_tmp;
            p_st_session->i_cli_tds_max_ver = p_st_req->i_cli_tds_min_ver_tmp;
        }
        else /* 实际情况不会发生 */
        {
            if (p_st_session->i_cli_tds_min_ver == MSSQL_TDS_VER_74)
            {
                p_st_session->i_cli_tds_ver = MSSQL_TDS_VER_74;
                p_st_session->i_cli_tds_min_ver = MSSQL_TDS_VER_74;
                p_st_session->i_cli_tds_max_ver = MSSQL_TDS_VER_74;
            }
            else
            {
                p_st_session->i_cli_tds_min_ver = p_st_req->i_cli_tds_min_ver_tmp;
                p_st_session->i_cli_tds_max_ver = MSSQL_TDS_VER_74;
            }
        }
    }

    return;
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_Cursor(1)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor(Conntrack *p_st_conn
                         , L7session_sqlserver_private *p_st_private
                         , Frhash_header *p_st_hash_report
                         , int i_cancel_flg
                         , int i_whole_flg)
{
    /* todo未截取到数据包, 还未支持 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_Cursor: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置cancel信息 */
    p_st_private->p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_private->p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  ProcID为CursorOpen(2)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_open(Conntrack *p_st_conn
                             , L7session_sqlserver_private *p_st_private
                             , Frhash_header *p_st_hash_report
                             , int i_cancel_flg
                             , int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得一个parameter */
        if (p_st_req->ui_bind_count == 1)
        {
            i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                           , &(p_st_req->i_cli_tds_min_ver_tmp)
                                           , &p_st_value, &i_ref_flg);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("Parse RPC parameter failed or need more data!\n");
                return i_ret;
            }

            /* 创建statement */
            p_st_statement = frdb_create_statement();
            if (p_st_statement == NULL)
            {
                frdbg("frdb_create_statement failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            frdb_statement_used(p_st_statement);
	        /* 创建resultset */
	        ul_req_sequence = frct_seq_increase(p_st_conn);
	        p_st_resultset = frdb_create_resultset(ul_req_sequence);
	        if (p_st_resultset == NULL)
	        {
	            frdbg("frdb_create_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 追加结果集到statement */
	        i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            frdb_resultset_free(&p_st_resultset);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 创建Sql_field_bind */
	        p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
	        if (p_st_bind == NULL)
	        {
	            frdbg("Create Sql_field_bind failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }
	        memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

	        /* 设置bind list参数 */
	        i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset_bind failed!\n");
	            frfree(p_st_bind);
	            return APM_L7_ANALYZE_FAIL;
	        }

            /* 设置request的statement和resultset索引 */
            p_st_req->p_st_statement = p_st_statement;
            p_st_req->p_st_resultset = p_st_resultset;
            p_st_req->p_st_bind = p_st_bind;

            /* 设置sql */
            frdb_set_sql(p_st_statement, p_st_value->p_field_value);
            /* 将取出SQl语句内存赋值给request结构体，内存留待释放request结构体时释放 */
            p_st_value->p_field_value = NULL;
            /* 释放prepare信息 */
            sqlserver_frdata_free(&p_st_value);
        }
        else
        {
            i_ret = sqlserver_skip_rpc_param(p_st_data, i_whole_flg
                                            , &(p_st_req->i_cli_tds_min_ver_tmp)
                                            , &i_ref_flg);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("Parse RPC parameter failed or need more data!\n");
                return i_ret;
            }
        }

        /* 设置解析到的位置 */
        ui_position = bytebuff_getPosition(p_st_data);
        p_st_fragment->ui_parsed_index = ui_position;
        p_st_req->ui_bind_count += 1;
    }

    /* 查看是否结束 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorPrepExec: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    p_st_statement = p_st_req->p_st_statement;
    p_st_resultset = p_st_req->p_st_resultset;

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));

    //frdbg("Parse Sp_CursorPrepExec success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorExecute(4)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_exec(Conntrack *p_st_conn
                             , L7session_sqlserver_private *p_st_private
                             , Frhash_header *p_st_hash_report
                             , int i_cancel_flg
                             , int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    long l_prepare_id = 0;
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    Frlist_node *p_st_node = NULL;
    Frdata_field *p_st_value = NULL;
    Frlist_node *p_hash_node = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得一个parameter */
        i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                        , &(p_st_req->i_cli_tds_min_ver_tmp)
                                        , &p_st_value, &i_ref_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            if (i_ret == APM_L7_ANALYZE_FAIL && p_st_statement)
            {
                frdb_del_last_resultset(p_st_statement);
            }
            return i_ret;
        }

        /* 设置解析到的位置 */
        ui_position = bytebuff_getPosition(p_st_data);
        p_st_fragment->ui_parsed_index = ui_position;
        p_st_req->ui_bind_count += 1;

        /* 第一个参数是prepare ID */
        if (p_st_req->ui_bind_count == 1)
        {
            if ((p_st_value->em_data_type == FRINT
                || p_st_value->em_data_type == FRLONG)
                   && p_st_value->p_field_value)
            {
                l_prepare_id = atol(p_st_value->p_field_value);
                sqlserver_frdata_free(&p_st_value);
            }
            else // never happen?
            {
                frdbg("parameter incorrect!\n");
                sqlserver_frdata_free(&p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }

            /* 到hash表中找到对应的prepare语句 */
            p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                         , l_prepare_id);
            /* 取得statement数据 */
            p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
            if (p_st_statement == NULL)
            {
                frdbg("No matching prepare statement!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            /* 取得结果集信息,第一次计算时间要将prepare的也计算在内 */
            if (frdb_is_first_result(p_st_statement))
            {
                frdb_statement_used(p_st_statement);
                p_st_resultset = frdb_get_last_resultset(p_st_statement);
                if (p_st_resultset == NULL)
                {
                    frdbg("Get resultset failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                /* 创建结果集 */
                ul_req_sequence = frct_seq_increase(p_st_conn);
                p_st_resultset = frdb_create_resultset(ul_req_sequence);
                if (p_st_resultset == NULL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 追加结果集到statement */
                i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
                if (i_ret != FR_SUCC)
                {
                    frdb_resultset_free(&p_st_resultset);
                    return APM_L7_ANALYZE_FAIL;
                }
            }

            /* 设置request的statement和resultset索引 */
            p_st_req->p_st_statement = p_st_statement;
            p_st_req->p_st_resultset = p_st_resultset;

            /* 创建Sql_field_bind */
            p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
            if (p_st_bind == NULL)
            {
                frdb_del_last_resultset(p_st_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

            /* 设置sql bind 参数 */
            i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_bind);
                frdb_del_last_resultset(p_st_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            p_st_req->p_st_bind = p_st_bind;
        }
        /* 第六个以及以上是bind的参数 */
        else if (p_st_req->ui_bind_count >= 6)
        {
            /* 取得statement和resultset和bind field */
            p_st_statement = p_st_req->p_st_statement;
            p_st_resultset = p_st_req->p_st_resultset;
            p_st_bind = p_st_req->p_st_bind;
            /* 设置参数名称 */
            p_st_node = frlist_node_create(p_st_value);
            if (p_st_node == NULL)
            {
                sqlserver_frdata_free(&p_st_value);
                frdb_del_last_resultset(p_st_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            frlist_push(&p_st_bind->st_field_list, p_st_node);
        }
        /* 其他的参数忽略 */
        else
        {
            sqlserver_frdata_free(&p_st_value);
        }
    }

    /* 查看是否结束 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorExecute: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                            , p_st_fragment->ui_total_len
                            , &(p_st_fragment->st_first_timestamp)
                            , &(p_st_fragment->st_end_timestamp));

    /* 不是select直接上报 */
    if (sqlserver_select_chk(p_st_statement->p_sql) == FR_NO)
    {
        /* 创建report body */
        p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_sess);
        /* 创建report body失败时，不释放做成的request */
        if (p_st_report_body == NULL)
        {
            frdbg("sqlserver_new_report_body failed!\n");
            return APM_L7_ANALYZE_SUCC;
        }
        /* 上报request数据 */
        i_ret = frdb_report_req2(p_st_conn, p_st_hash_report, p_st_statement
                                 , p_st_resultset, &p_st_report_body);
        /* 上报request数据失败时，不释放做成的request */
        if (i_ret != FR_SUCC)
        {
            frdbg("frdb_report_req2 failed!\n");
            frreport_body_free(&p_st_report_body);
            return APM_L7_ANALYZE_SUCC;
        }
    }

    //frdbg("Parse Sp_CursorExecute success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorPrepExec(5)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_prep_exec(Conntrack *p_st_conn
                                  , L7session_sqlserver_private *p_st_private
                                  , Frhash_header *p_st_hash_report
                                  , int i_cancel_flg
                                  , int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    Frlist_node *p_st_node = NULL;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得一个parameter */
        i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                        , &(p_st_req->i_cli_tds_min_ver_tmp)
                                        , &p_st_value, &i_ref_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("Parse RPC parameter failed or need more data!\n");
            return i_ret;
        }

        /* 设置解析到的位置 */
        ui_position = bytebuff_getPosition(p_st_data);
        p_st_fragment->ui_parsed_index = ui_position;
        p_st_req->ui_bind_count += 1;

        /* 取得第一个参数时创建statement和resultset */
        if (p_st_req->ui_bind_count == 1)
        {
            sqlserver_frdata_free(&p_st_value);
            /* 创建statement */
            p_st_statement = frdb_create_statement();
            if (p_st_statement == NULL)
            {
                frdbg("frdb_create_statement failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            frdb_statement_used(p_st_statement);
	        /* 创建resultset */
	        ul_req_sequence = frct_seq_increase(p_st_conn);
	        p_st_resultset = frdb_create_resultset(ul_req_sequence);
	        if (p_st_resultset == NULL)
	        {
	            frdbg("frdb_create_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 追加结果集到statement */
	        i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            frdb_resultset_free(&p_st_resultset);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 创建Sql_field_bind */
	        p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
	        if (p_st_bind == NULL)
	        {
	            frdbg("Create Sql_field_bind failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }
	        memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

	        /* 设置bind list参数 */
	        i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset_bind failed!\n");
	            frfree(p_st_bind);
	            return APM_L7_ANALYZE_FAIL;
	        }

            /* 设置request的statement和resultset索引 */
            p_st_req->p_st_statement = p_st_statement;
            p_st_req->p_st_resultset = p_st_resultset;
            p_st_req->p_st_bind = p_st_bind;
        }
        /* 第二个参数是参数列表  */
        else if (p_st_req->ui_bind_count == 3)
        {
            //frdbg("parameter list:[%s]\n", p_st_value->p_field_value);
            sqlserver_frdata_free(&p_st_value);
        }
        /* 第三个参数是SQL语句  */
        else if (p_st_req->ui_bind_count == 4)
        {
            p_st_statement = p_st_req->p_st_statement;
            /* 设置sql */
            frdb_set_sql(p_st_statement, p_st_value->p_field_value);
            /* 将取出SQl语句内存赋值给request结构体，内存留待释放request结构体时释放 */
            p_st_value->p_field_value = NULL;
            /* 释放prepare信息 */
            sqlserver_frdata_free(&p_st_value);
        }
        /* 第8个已经以上参数都是BIND的具体值  */
        else if (p_st_req->ui_bind_count >= 8)
        {
            /* 取得bind参数列表 */
            p_st_bind = p_st_req->p_st_bind;
            p_st_node = frlist_node_create(p_st_value);
            if (p_st_node == NULL)
            {
                sqlserver_frdata_free(&p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            frlist_push(&p_st_bind->st_field_list, p_st_node);
        }
        else
        {
            sqlserver_frdata_free(&p_st_value);
        }
    }

    /* 查看是否结束 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorPrepExec: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    p_st_statement = p_st_req->p_st_statement;
    p_st_resultset = p_st_req->p_st_resultset;

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));

    /* 不是select直接上报 */
    if (sqlserver_select_chk(p_st_statement->p_sql) == FR_NO)
    {
        /* 创建report body */
        p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_sess);
        /* 创建report body失败时，不释放做成的request */
        if (p_st_report_body == NULL)
        {
            frdbg("sqlserver_new_report_body failed!\n");
            return APM_L7_ANALYZE_SUCC;
        }
        /* 上报request数据 */
        i_ret = frdb_report_req2(p_st_conn, p_st_hash_report, p_st_statement
                                 , p_st_resultset, &p_st_report_body);
        /* 上报request数据失败时，不释放做成的request */
        if (i_ret != FR_SUCC)
        {
            frdbg("frdb_report_req2 failed!\n");
            frreport_body_free(&p_st_report_body);
            return APM_L7_ANALYZE_SUCC;
        }
    }

    //frdbg("Parse Sp_CursorPrepExec success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorUnprepare(6)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_unprep(Conntrack *p_st_conn
                                , L7session_sqlserver_private *p_st_private
                                , Frhash_header *p_st_hash_report
                                , int i_cancel_flg
                                , int i_whole_flg)
{
    /* Sp_Unprepare没有大数据包,等待所有数据接收完了解析 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorUnprepare: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    long l_prepare_id = 0;
    Frdata_field *p_st_value = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 取得parameter */
    i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                   , &(p_st_req->i_cli_tds_min_ver_tmp)
                                   , &p_st_value, &i_ref_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Parse RPC parameter failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* Sp_Unprepare有唯一的一个parameter描述prepare ID */
    if (bytebuff_remaining(p_st_data) == 0
        && ((p_st_value->em_data_type == FRINT
            || p_st_value->em_data_type == FRLONG)
               && p_st_value->p_field_value))
    {
        l_prepare_id = atol(p_st_value->p_field_value);
        sqlserver_frdata_free(&p_st_value);
    }
    else // never happen?
    {
        frdbg("parameter incorrect!\n");
        sqlserver_frdata_free(&p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    /* 设置prepare ID */
    p_st_req->l_uid = l_prepare_id;

    //frdbg("Parse Sp_CursorUnprepare success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorFetch(7)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_fetch(Conntrack *p_st_conn
                              , L7session_sqlserver_private *p_st_private
                              , Frhash_header *p_st_hash_report
                              , int i_cancel_flg
                              , int i_whole_flg)
{
    /* fetch时不会出现大数据,接收完之后统一解析 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorFetch: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    int i_loop = 0;
    unsigned char uc_flag = 0;
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    int i_first_batch_flg = FR_YES;
    long l_cursor_id = 0;
    Frdata_field *p_st_value = NULL;           /* 解析出来的参数值 */
    Frlist_node *p_hash_node = NULL;
    Mssql_cursor *p_st_cursor = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得第一个parameter, 用以取得cursor ID */
        if (i_first_batch_flg == FR_YES && i_loop == 0)
        {
            i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                           , &(p_st_req->i_cli_tds_min_ver_tmp)
                                           , &p_st_value, &i_ref_flg);
        }
        /* 其他参数直接跳过 */
        else
        {
            i_ret = sqlserver_skip_rpc_param(p_st_data, i_whole_flg
                                            , &(p_st_req->i_cli_tds_min_ver_tmp)
                                            , &i_ref_flg);

        }
        /* 解析错误 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("Parse parameter failed!\n");
            sqlserver_frdata_free(&p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        i_loop++;

        /* 解析完了 */
        if (bytebuff_remaining(p_st_data) == 0)
        {
            break;
        }

        /* 判断当前是不是BatchFlag或者NoExecFlag */
        // BatchFlag = %x80 / %xFF ; (Changed to %xFF in TDS 7.2)
        // NoExecFlag = %xFE ; (introduced in TDS 7.2)
        bytebuff_peek_char(p_st_data, &uc_flag);
        if (uc_flag == 0x80 || uc_flag == 0xFF || uc_flag == 0xFE)
        {
            i_loop = 0;
            i_first_batch_flg = FR_NO;
            /* 设置可能版本号 */
            if ((uc_flag == 0xFF || uc_flag == 0xFE)
                 && p_st_req->i_cli_tds_min_ver_tmp < MSSQL_TDS_VER_72)
            {
                p_st_req->i_cli_tds_min_ver_tmp = MSSQL_TDS_VER_72;
            }

            /* 最后一个BatchFlag或者NoExecFlag */
            if (bytebuff_remaining(p_st_data) == 1)
            {
                break;
            }
            /* FLAG + ProcIDSwitch + ProcID + OptionFlags */
            else if (bytebuff_remaining(p_st_data) < 1 + 2 + 2 + 2)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                bytebuff_skip(p_st_data, 7);
            }
        }
    }

    /* 取得cursor ID */
    if ((p_st_value->em_data_type == FRINT
        || p_st_value->em_data_type == FRLONG)
           && p_st_value->p_field_value)
    {
        l_cursor_id = atol(p_st_value->p_field_value);
    }
    else // never happen?
    {
        frdbg("Parameter incorrect!\n");
        sqlserver_frdata_free(&p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }
    sqlserver_frdata_free(&p_st_value);

    /* 根据cursor ID取得对应的cursor信息 */
    p_st_cursor = sqlserver_get_cursor_info(&(p_st_private->list_cursor)
                                           , l_cursor_id);
    if (p_st_cursor == NULL)
    {
        /* 到hash表中找到对应的prepare语句 */
        p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                     , l_cursor_id);
        /* 取得statement数据 */
        p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
        if (p_st_statement == NULL)
        {
            frdbg("No matching prepare statement!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得结果集信息, 一个Sp_Prepare ID只有一个结果集 */
        p_st_resultset = frdb_get_last_resultset(p_st_statement);
        if (p_st_resultset == NULL)
        {
            frdbg("Get resultset failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        /* 取得statement和resultset的索引 */
        p_st_statement = p_st_cursor->p_st_statement;
        p_st_resultset = p_st_cursor->p_st_resultset;
    }

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));
    /* 设置statement和resultset的索引 */
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;

    /* 设置TDS版本号 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 设置出力 */
    //frdbg("Parse Sp_CursorFetch success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorOption(8)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_opt(Conntrack *p_st_conn
                            , L7session_sqlserver_private *p_st_private
                            , Frhash_header *p_st_hash_report
                            , int i_cancel_flg
                            , int i_whole_flg)
{
    /* todo未截取到数据包, 还未支持 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorOption: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置cancel信息 */
    p_st_private->p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_private->p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_CursorClose(9)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_cursor_close(Conntrack *p_st_conn
                              , L7session_sqlserver_private *p_st_private
                              , Frhash_header *p_st_hash_report
                              , int i_cancel_flg
                              , int i_whole_flg)
{
    /* fetch时不会出现大数据,接收完之后统一解析 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_CursorClose: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    long l_cursor_id = 0;
    Frdata_field *p_st_value = NULL;           /* 解析出来的参数值 */
    Frlist_node *p_hash_node = NULL;
    Mssql_cursor *p_st_cursor = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 取得parameter */
    i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                    , &(p_st_req->i_cli_tds_min_ver_tmp)
                                    , &p_st_value, &i_ref_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Parse parameter failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    if (bytebuff_remaining(p_st_data) == 0
        && ((p_st_value->em_data_type == FRINT
        || p_st_value->em_data_type == FRLONG)
           && p_st_value->p_field_value))
    {
        l_cursor_id = atol(p_st_value->p_field_value);
    }
    else // never happen?
    {
        frdbg("Parameter incorrect!\n");
        sqlserver_frdata_free(&p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }
    sqlserver_frdata_free(&p_st_value);

    /* 根据cursor ID取得对应的cursor信息 */
    p_st_cursor = sqlserver_get_cursor_info(&(p_st_private->list_cursor)
                                              , l_cursor_id);
    if (p_st_cursor == NULL)
    {
        /* 到hash表中找到对应的prepare语句 */
        p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                     , l_cursor_id);
        /* 取得statement数据 */
        p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
        if (p_st_statement == NULL)
        {
            frdbg("No matching prepare statement!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得结果集信息, 一个Sp_Prepare ID只有一个结果集 */
        p_st_resultset = frdb_get_last_resultset(p_st_statement);
        if (p_st_resultset == NULL)
        {
            frdbg("Get resultset failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        /* 取得statement和resultset的索引 */
        p_st_statement = p_st_cursor->p_st_statement;
        p_st_resultset = p_st_cursor->p_st_resultset;
    }

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));
    /* 设置statement和resultset */
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    p_st_req->l_uid = l_cursor_id;

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 创建report body */
    p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        return APM_L7_ANALYZE_SUCC;
    }
    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report, p_st_statement
                             , p_st_resultset, &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    //frdbg("Parse Sp_CursorClose success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_ExecuteSql(10)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (succ)
*              APM_L7_ANALYZE_TODO       (todo)
*              APM_L7_ANALYZE_FAIL       (fail)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_exec_sql(Conntrack *p_st_conn
                          , L7session_sqlserver_private *p_st_private
                          , Frhash_header *p_st_hash_report
                          , int i_cancel_flg
                          , int i_whole_flg)
{
    /* todo未截取到数据包, 还未支持 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_ExecuteSql: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置cancel信息 */
    p_st_private->p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_private->p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  ProcID为Prepare(3,11)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_prep(Conntrack *p_st_conn
                      , L7session_sqlserver_private *p_st_private
                      , Frhash_header *p_st_hash_report
                      , int i_cancel_flg
                      , int i_whole_flg)
{
    /* Prepare时不会出现大数据,接收完之后统一解析 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_Prepare/Sp_CursorPrepare: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    int i_loop = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    unsigned long ul_req_sequence = 0;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frdata_field *p_st_param_statement = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析Sp_Prepare/Sp_CursorPrepare */
    while (bytebuff_remaining(p_st_data))
    {
        i_loop++;
        /* 第三个参数的值是Prepare SQL语句 */
        if (i_loop == 3)
        {
            /* 取得Prepare SQL语句 */
            i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                           , &(p_st_req->i_cli_tds_min_ver_tmp)
                                           , &p_st_param_statement, &i_ref_flg);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("sqlserver_get_rpc_param failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /* 忽略其他参数 */
        else
        {
            i_ret = sqlserver_skip_rpc_param(p_st_data, i_whole_flg
                                            , &(p_st_req->i_cli_tds_min_ver_tmp)
                                            , &i_ref_flg);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frdbg("sqlserver_skip_rpc_param failed!\n");
                sqlserver_frdata_free(&p_st_param_statement);
                return APM_L7_ANALYZE_FAIL;
            }
        }
    }

    /* 查看取出类型是否合理 */
    if (p_st_param_statement->em_data_type != FRSTRING) //never happen?
    {
        frdbg("Get sql statement failed!\n");
        sqlserver_frdata_free(&p_st_param_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 创建statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        sqlserver_frdata_free(&p_st_param_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设置sql */
    frdb_set_sql(p_st_statement, p_st_param_statement->p_field_value);
    /* 将取出SQl语句内存赋值给request结构体，内存留待释放request结构体时释放 */
    p_st_param_statement->p_field_value = NULL;
    /* 释放prepare信息 */
    sqlserver_frdata_free(&p_st_param_statement);

    /* 创建结果 */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdb_statement_free(&p_st_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 追加结果集到statement */
    i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
    if (i_ret != FR_SUCC)
    {
        frdb_statement_free(&p_st_statement);
        frdb_resultset_free(&p_st_resultset);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                            , p_st_fragment->ui_total_len
                            , &(p_st_fragment->st_first_timestamp)
                            , &(p_st_fragment->st_end_timestamp));

    /* 设置request索引 */
    p_st_req->p_st_statement = p_st_statement;
    p_st_req->p_st_resultset = p_st_resultset;
    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    //frdbg("Parse Sp_Prepare success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_Execute(12)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_exec(Conntrack *p_st_conn
                      , L7session_sqlserver_private *p_st_private
                      , Frhash_header *p_st_hash_report
                      , int i_cancel_flg
                      , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_loop = 0;
    uint8_t u8_flg = 0;
    long l_prepare_id = 0;
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    int i_first_param_flg = FR_YES;
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_hash_node = NULL;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 判断是否有剩余长度 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得一个parameter */
        i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                       , &(p_st_req->i_cli_tds_min_ver_tmp)
                                       , &p_st_value, &i_ref_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdb_field_bind_free(&p_st_bind);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                frdb_init_resultset(p_st_resultset
                                   , frct_seq_increase(p_st_conn));
            }
            return i_ret;
        }

        /* 第一个parameter是用来定位prepare语句的 */
        if (i_first_param_flg == FR_YES)
        {
            i_first_param_flg = FR_NO;
            if ((p_st_value->em_data_type == FRINT
                || p_st_value->em_data_type == FRLONG)
                   && p_st_value->p_field_value)
            {
                l_prepare_id = atol(p_st_value->p_field_value);
            }
            else // never happen?
            {
                frdbg("parameter incorrect!\n");
                sqlserver_frdata_free(&p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            sqlserver_frdata_free(&p_st_value);

            /* 是否是第一次取得prepare ID */
            if (p_st_req->p_st_statement == NULL)
            {
                /* 到hash表中找到对应的prepare语句 */
                p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                             , l_prepare_id);
                /* 取得statement数据 */
                p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
                if (p_st_statement == NULL)
                {
                    frdbg("No matching prepare statement!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 取得结果集信息, 一个Sp_Prepare ID只有一个结果集 */
                p_st_resultset = frdb_get_last_resultset(p_st_statement);
                if (p_st_resultset == NULL)
                {
                    frdbg("Get resultset failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 设置request索引 */
                p_st_req->p_st_statement = p_st_statement;
                p_st_req->p_st_resultset = p_st_resultset;
            }
            else /* 取出索引值 */
            {
                p_st_statement = p_st_req->p_st_statement;
                p_st_resultset = p_st_req->p_st_resultset;
            }

            /* 重新设置请求sequence ID */
            if (!(frdb_is_first_result(p_st_statement)))
            {
                ul_req_sequence = frct_seq_increase(p_st_conn);
                frdb_set_req_sequence2(p_st_resultset, ul_req_sequence);
            }

            /* 创建Sql_field_bind */
            p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
            if (p_st_bind == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_st_bind, 0x0, sizeof(Sql_field_bind));
        }
        else
        {
            /* unsigned int最大值是4294967295, 11是4294967295加一个空格的长度 */
            p_st_node = frlist_node_create(p_st_value);
            if (p_st_node == NULL)
            {
                sqlserver_frdata_free(&p_st_value);
                frdb_field_bind_free(&p_st_bind);
                frdb_init_resultset(p_st_resultset
                                   , frct_seq_increase(p_st_conn));
                return APM_L7_ANALYZE_FAIL;
            }
            frlist_push(&(p_st_bind->st_field_list), p_st_node);
        }

        /* 看是否还有遗留数据 */
        if (bytebuff_remaining(p_st_data))
        {
            /* 取得一个字符 */
            i_ret = bytebuff_peek_char(p_st_data, &u8_flg);
            if (i_ret != FR_SUCC)
            {
                frdb_field_bind_free(&p_st_bind);
                frdb_init_resultset(p_st_resultset
                                   , frct_seq_increase(p_st_conn));
                return APM_L7_ANALYZE_FAIL;
            }
        }
        else
        {
            /* 所有数据包已经接收完了 */
            if (i_whole_flg == FR_YES)
            {
                /* 参数列表 */
                p_st_node = frlist_node_create(p_st_bind);
                if (p_st_node == NULL)
                {
                    frdb_field_bind_free(&p_st_bind);
                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    return APM_L7_ANALYZE_FAIL;
                }
                frlist_push(&p_st_resultset->st_bind_list, p_st_node);
                break;
            }
            else
            {
                frdb_field_bind_free(&p_st_bind);
                return APM_L7_ANALYZE_TODO;
            }
        }

        /* 判断当前是不是BatchFlag或者NoExecFlag */
        // BatchFlag = %x80 / %xFF ; (Changed to %xFF in TDS 7.2)
        // NoExecFlag = %xFE ; (introduced in TDS 7.2)
        if (u8_flg == 0x80 || u8_flg == 0xFF || u8_flg == 0xFE)
        {
            /* 重置 */
            i_loop = 0;
            i_first_param_flg = FR_YES;

            /* 设置可能版本号 */
            if ((u8_flg == 0xFF || u8_flg == 0xFE)
                && p_st_req->i_cli_tds_min_ver_tmp < MSSQL_TDS_VER_72)
            {
                p_st_req->i_cli_tds_min_ver_tmp = MSSQL_TDS_VER_72;
            }

            /* FLAG + ProcIDSwitch + ProcID + OptionFlags */
            if (bytebuff_remaining(p_st_data) >= 1 + 2 + 2 + 2)
            {
                /* 追加参数列表 */
                p_st_node = frlist_node_create(p_st_bind);
                if (p_st_node == NULL)
                {
                    frdb_field_bind_free(&p_st_bind);
                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    return APM_L7_ANALYZE_FAIL;
                }
                p_st_bind = NULL;
                frlist_push(&p_st_resultset->st_bind_list, p_st_node);
                /* 跳过FLAG,ProcIDSwitch,ProcID,OptionFlags */
                bytebuff_skip(p_st_data, 1 + 2 + 2 + 2);
                /* 设置解析到的位置 */
                ui_position = bytebuff_getPosition(p_st_data);
                p_st_fragment->ui_parsed_index = ui_position;
            }
            else if (bytebuff_remaining(p_st_data) == 1)
            {
                /* 所有数据包已经接收完了 */
                if (i_whole_flg == FR_YES)
                {
                    /* 追加参数列表 */
                    p_st_node = frlist_node_create(p_st_bind);
                    if (p_st_node == NULL)
                    {
                        frdb_field_bind_free(&p_st_bind);
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        return APM_L7_ANALYZE_FAIL;
                    }
                    frlist_push(&p_st_resultset->st_bind_list, p_st_node);
                    break;
                }
                else
                {
                    frdbg("Packet Sp_Execute: need more data!\n");
                    frdb_field_bind_free(&p_st_bind);
                    return APM_L7_ANALYZE_TODO;
                }
            }
            else
            {
                frdb_field_bind_free(&p_st_bind);
                if (i_whole_flg == FR_YES)
                {
                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    frdbg("Packet Sp_Execute: need more data!\n");
                    return APM_L7_ANALYZE_TODO;
                }
            }
        }
    }

    /* 还有后续的数据包 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_Execute: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));
    /* 设置TDS版本号 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 创建report body */
    p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        return APM_L7_ANALYZE_SUCC;
    }
    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report, p_st_statement
                             , p_st_resultset, &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    //frdbg("Parse Sp_Execute success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_PrepExec(13)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_prepexec(Conntrack *p_st_conn
                          , L7session_sqlserver_private *p_st_private
                          , Frhash_header *p_st_hash_report
                          , int i_cancel_flg
                          , int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    Frlist_node *p_st_node = NULL;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得一个parameter */
        i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                       , &(p_st_req->i_cli_tds_min_ver_tmp)
                                       , &p_st_value, &i_ref_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("Parse RPC parameter failed or need more data!\n");
            return i_ret;
        }

        /* 设置解析到的位置 */
        ui_position = bytebuff_getPosition(p_st_data);
        p_st_fragment->ui_parsed_index = ui_position;
        p_st_req->ui_bind_count += 1;

        /* 取得第一个参数时创建statement和resultset */
        if (p_st_req->ui_bind_count == 1)
        {
            sqlserver_frdata_free(&p_st_value);
            /* 创建statement */
            p_st_statement = frdb_create_statement();
            if (p_st_statement == NULL)
            {
                frdbg("frdb_create_statement failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            frdb_statement_used(p_st_statement);
	        /* 创建resultset */
	        ul_req_sequence = frct_seq_increase(p_st_conn);
	        p_st_resultset = frdb_create_resultset(ul_req_sequence);
	        if (p_st_resultset == NULL)
	        {
	            frdbg("frdb_create_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 追加结果集到statement */
	        i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset failed!\n");
	            frdb_statement_free(&p_st_statement);
	            frdb_resultset_free(&p_st_resultset);
	            return APM_L7_ANALYZE_FAIL;
	        }

	        /* 创建Sql_field_bind */
	        p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
	        if (p_st_bind == NULL)
	        {
	            frdbg("Create Sql_field_bind failed!\n");
	            frdb_statement_free(&p_st_statement);
	            return APM_L7_ANALYZE_FAIL;
	        }
	        memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

	        /* 设置bind list参数 */
	        i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
	        if (i_ret != FR_SUCC)
	        {
	            frdbg("frdb_add_resultset_bind failed!\n");
	            frfree(p_st_bind);
	            return APM_L7_ANALYZE_FAIL;
	        }

            /* 设置request的statement和resultset索引 */
            p_st_req->p_st_statement = p_st_statement;
            p_st_req->p_st_resultset = p_st_resultset;
            p_st_req->p_st_bind = p_st_bind;
        }
        /* 第二个参数是参数列表  */
        else if (p_st_req->ui_bind_count == 2)
        {
            //frdbg("parameter list:[%s]\n", p_st_value->p_field_value);
            sqlserver_frdata_free(&p_st_value);
        }
        /* 第三个参数是SQL语句  */
        else if (p_st_req->ui_bind_count == 3)
        {
            p_st_statement = p_st_req->p_st_statement;
            /* 设置sql */
            frdb_set_sql(p_st_statement, p_st_value->p_field_value);
            /* 将取出SQl语句内存赋值给request结构体，内存留待释放request结构体时释放 */
            p_st_value->p_field_value = NULL;
            /* 释放prepare信息 */
            sqlserver_frdata_free(&p_st_value);
        }
        /* 其他参数都是BIND的具体值  */
        else
        {
            /* 取得bind参数列表 */
            p_st_bind = p_st_req->p_st_bind;
            p_st_node = frlist_node_create(p_st_value);
            if (p_st_node == NULL)
            {
                sqlserver_frdata_free(&p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            frlist_push(&p_st_bind->st_field_list, p_st_node);
        }
    }

    /* 查看是否结束 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_PrepExec: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_req->p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));

    /* 创建report body */
    p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        return APM_L7_ANALYZE_SUCC;
    }
    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                             , p_st_req->p_st_statement
                             , p_st_req->p_st_resultset
                             , &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    //frdbg("Parse Sp_PrepExec succ!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_PrepExecRpc(14)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_prep_rpc(Conntrack *p_st_conn
                          , L7session_sqlserver_private *p_st_private
                          , Frhash_header *p_st_hash_report
                          , int i_cancel_flg
                          , int i_whole_flg)
{
    /* todo未截取到数据包, 还未支持 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_PrepExecRpc: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置cancel信息 */
    p_st_private->p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_private->p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  ProcID为Sp_Unprepare(15)的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_unprep(Conntrack *p_st_conn
                        , L7session_sqlserver_private *p_st_private
                        , Frhash_header *p_st_hash_report
                        , int i_cancel_flg
                        , int i_whole_flg)
{
    /* Sp_Unprepare没有大数据包,等待所有数据接收完了解析 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet Sp_Unprepare: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;
    long l_prepare_id = 0;
    Frdata_field *p_st_value = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 取得parameter */
    i_ret = sqlserver_get_rpc_param(p_st_data, p_st_sess, i_whole_flg
                                   , &(p_st_req->i_cli_tds_min_ver_tmp)
                                   , &p_st_value, &i_ref_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("Parse RPC parameter failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* Sp_Unprepare有唯一的一个parameter描述prepare ID */
    if (bytebuff_remaining(p_st_data) == 0
        && ((p_st_value->em_data_type == FRINT
            || p_st_value->em_data_type == FRLONG)
               && p_st_value->p_field_value))
    {
        l_prepare_id = atol(p_st_value->p_field_value);
        sqlserver_frdata_free(&p_st_value);
    }
    else // never happen?
    {
        frdbg("Parameter incorrect!\n");
        sqlserver_frdata_free(&p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置版本信息 */
    __sqlserver_set_tds_ver(p_st_req, p_st_sess);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;
    /* 设置prepare ID */
    p_st_req->l_uid = l_prepare_id;

    //frdbg("Parse Sp_Unprepare success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  用ProcName的RPCReqBatch解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(sqlserver私有信息)
            :  p_st_hash_report(report信息)
            :  i_whole_flg(packet完整性flag)
*  RTN      :  APM_L7_ANALYZE_SUCC       (success)
*              APM_L7_ANALYZE_TODO       (need more data)
*              APM_L7_ANALYZE_FAIL       (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_rpc_name(Conntrack *p_st_conn
                      , L7session_sqlserver_private *p_st_private
                      , Frhash_header *p_st_hash_report
                      , int i_cancel_flg
                      , int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_ref_flg = MSSQL_INPUT_PARAM;       /* 入参还是出参标志 */
    unsigned int ui_position = 0;
    unsigned long ul_req_sequence = 0;
    unsigned char uc_flag = 0;
    Frdata_field *p_st_value = NULL;
    Frlist_node *p_st_node = NULL;
    Sql_field_bind *p_st_bind = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    Frlist_header st_bind_list;
    memset(&st_bind_list, 0x0, sizeof(Frlist_header));
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7session_sqlserver *p_st_session = p_st_private->p_st_sess;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 是否需要新创建resultset */
    if (p_st_req->p_st_resultset == NULL)
    {
        /* 创建resultset */
        ul_req_sequence = frct_seq_increase(p_st_conn);
        p_st_resultset = frdb_create_resultset(ul_req_sequence);
        if (p_st_resultset == NULL)
        {
            frdbg("frdb_create_resultset failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }

        /* 追加结果集到statement */
        i_ret = frdb_add_resultset(p_st_req->p_st_statement, p_st_resultset);
        if (i_ret != FR_SUCC)
        {
            frdbg("frdb_create_resultset failed!\n");
            frdb_resultset_free(&p_st_resultset);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 设置resultset索引 */
        p_st_req->p_st_resultset = p_st_resultset;

        /* 创建Sql_field_bind */
        p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
        if (p_st_bind == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

        /* 设置bind list参数 */
        i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
        if (i_ret != FR_SUCC)
        {
            frdbg("frdb_add_resultset_bind failed!\n");
            frfree(p_st_bind);
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        p_st_resultset = p_st_req->p_st_resultset;
        /* 取得之前的参数列表 */
        //p_st_node = frlist_node_idx(&p_st_resultset->st_bind_list, 0);
        p_st_node = FRLIST_LAST_NODE(&p_st_resultset->st_bind_list);
        p_st_bind = (Sql_field_bind *)FRLIST_GET_NODE_DATA(p_st_node);
        /* 正常情况下不会发生 */
        if (p_st_bind == NULL)
        {
            frdbg("Get bind field failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }

    while (bytebuff_remaining(p_st_data))
    {
        bytebuff_peek_char(p_st_data, &uc_flag);
        /* 下一个rpc */
        if (uc_flag == 0x80 || uc_flag == 0xFF || uc_flag == 0xFE)
        {
            bytebuff_skip(p_st_data, 1);
            /* skip name */
            uint16_t u16_length = 0;
            if (bytebuff_remaining(p_st_data) < 2)
            {
                p_st_fragment->ui_parsed_index += 1;
                break;
            }
            i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                                       , &u16_length, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (bytebuff_remaining(p_st_data) < (int)(u16_length * 2 + 2))
            {
                break;
            }
            bytebuff_skip(p_st_data, u16_length * 2 + 2);

            /* 创建Sql_field_bind */
            p_st_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
            if (p_st_bind == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_st_bind, 0x0, sizeof(Sql_field_bind));

            /* 设置bind list参数 */
            i_ret = frdb_add_resultset_bind(p_st_resultset, p_st_bind);
            if (i_ret != FR_SUCC)
            {
                frdbg("frdb_add_resultset_bind failed!\n");
                frfree(p_st_bind);
                return APM_L7_ANALYZE_FAIL;
            }
        }

        /* 取得一个parameter */
        i_ret = sqlserver_get_rpc_param(p_st_data, p_st_session, i_whole_flg
                                       , &(p_st_req->i_cli_tds_min_ver_tmp)
                                       , &p_st_value, &i_ref_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }

        /* 设置解析到的位置 */
        ui_position = bytebuff_getPosition(p_st_data);
        p_st_fragment->ui_parsed_index = ui_position;
        p_st_req->ui_bind_count += 1;

        p_st_node = frlist_node_create(p_st_value);
        if (p_st_node == NULL)
        {
            sqlserver_frdata_free(&p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(&p_st_bind->st_field_list, p_st_node);
    }

    /* 还有后续的数据包 */
    if (i_whole_flg != FR_YES)
    {
        frdbg("Packet ProcName: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_fragment->ui_total_len
                           , &(p_st_fragment->st_first_timestamp)
                           , &(p_st_fragment->st_end_timestamp));
    /* 设置TDS版本号 */
    __sqlserver_set_tds_ver(p_st_req, p_st_session);
    /* 设置cancel信息 */
    p_st_req->i_cancel_flg = i_cancel_flg;
    p_st_req->i_need_req_resp = MSSQL_RESPONSE;

    /* 创建report body */
    p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_session);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        return APM_L7_ANALYZE_SUCC;
    }
    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                             , p_st_req->p_st_statement
                             , p_st_req->p_st_resultset
                             , &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    //frdbg("Parse rpc name success!\n");
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}
